package com.jt.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

//1,AOP需要被Spring容器管理
@Component
//2.标识该类为AOP切面
@Aspect
public class SpringAOP {
    /**
     * 切入点表达式练习
     * 1.within(com.jt.*.DeptServiceImpl)   一级包下的类
     * 2.within(com.jt..*.DeptServiceImpl)  ..代表多级
     * 3.within(com.jt..*)  包下的所有的类
     * execution(* com.jt..*.DeptServiceImpl.add*())
     *
     * 1.(* com.jt..*.DeptServiceImpl.add*()) 返回值类型任意的，com.jt下的所有包中的DeptServiceImpl
     * 的类的add开头的方法，并且没有参数
     * 2.execution（* com.jt..*.*（..））
     * 注释：返回值类型任意，com.jt包下的所有包下的所有类的所有方法 任意参数
     *
     * 注解形式：@annotation(包名.注解名.)
     * */

    //1.定义before通知
//    @Before("bean(deptServiceImpl)")
//    @Before("within(com.jt.Service.DeptServiceImpl)")
    //@Before("execution(包名。类名。方法名。参数)")
//    @Before("execution(* com.jt..*.*(..))")
//    @Before("@annotation(com.jt.anno.Cache)")

    //1.定义切入点表达式
    @Pointcut("@annotation(com.jt.anno.Cache)")
    public void Pointcut(){

    }
//    @Before("Pointcut()")
    public void before(JoinPoint joinPoint){
        System.out.println("获取目标对象的类型："+joinPoint.getTarget().getClass());
        System.out.println("获取目标对象的类名："+joinPoint.getSignature().getDeclaringTypeName());
        System.out.println("获取目标对象方法名："+joinPoint.getSignature().getName());
        System.out.println("获取方法参数："+ Arrays.toString(joinPoint.getArgs()));

        System.out.println("我是before通知");
    }
//    @AfterReturning(pointcut = "Pointcut()",returning = "result")
    public void AfterReturning(JoinPoint joinPoint,Object result){
        System.out.println("我是AfterReturning通知");
        System.out.println("用户的返回值结果:"+result);
        System.out.println("获取方法参数："+ Arrays.toString(joinPoint.getArgs()));
    }
    @AfterThrowing(pointcut = "Pointcut()",throwing = "e")
    public void AfterThrowing(Exception e){
        System.out.println("我是AfterThrowing通知");
        System.out.println("获取异常信息:"+e.getMessage());
        System.out.println("获取异常类型:"+e.getClass());
    }
//    @After("Pointcut()")
    public void After(){
        System.out.println("我是After通知");
    }
    /**
     * 关于环绕通知说明
     * 作用：可以控制目标方法是否执行
     * 参数：ProceedingJoinPoint  通过proceed方法控制目标方法执行
     * return
     * */
    @Around("@annotation(com.jt.anno.Cache)")
    public Object around(ProceedingJoinPoint joinPoint){
        Object result=null;
        System.out.println("环绕通知开始");
        //1.执行下一个通知 2.执行目标方法 3.接收返回值
        try {
            long start = System.currentTimeMillis();
            Thread.sleep(2000);
            result = joinPoint.proceed();
            long end = System.currentTimeMillis();
            System.out.println("耗时:"+(end-start));
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("环绕通知结束");
        return result;
    }
}
